/**
 * ProfileController.java
 * Purpose: Controller
 *
 * @version 1.0 4/29/11
 * @author Hesham Massoud
 */

package controllers;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import com.sun.org.apache.bcel.internal.generic.IFNONNULL;

import play.cache.Cache;
import play.mvc.Controller;

import models.ActionLog;
import models.Comment;
import models.EEntity;
import models.Idea;
import models.IdeaRating;
import models.MergeRequest;
import models.Notification;
import models.Organization;
import models.Topic;
import models.User;

public class ProfileController extends Controller {

	/**
	 * Renders the merge request id for a page for the organizer to send a
	 * rejection mail to the merge request sender, to explain to him why he
	 * rejected the mail, if the merge request is equal to null the user is
	 * redirected to a page which shows a message that the idea is not found.
	 * 
	 * 
	 * @author Hesham Massoud
	 * 
	 * @story C3S42
	 * 
	 * @param requestId
	 *            The id of the merge request that is rejected.
	 * 
	 * */
	public static void sendRejectionMail(long requestId) {
		MergeRequest mRequest = MergeRequest.findById(requestId);
		notFoundIfNull(mRequest);
		render(mRequest);
	}

	/**
	 * Renders the merge request id for a page that contains, the merge report
	 * of the request, the two ideas to be merged,and options enabling the
	 * organizer/organization lead to merge the two ideas requested to be
	 * merged.
	 * 
	 * @author Hesham Massoud
	 * 
	 * @story C3S42
	 * 
	 * @param requestId
	 *            The id of the merge request that is rejected.
	 * 
	 * */
	public static void viewMergeIdeas(long requestId) {
		MergeRequest mRequest = MergeRequest.findById(requestId);
		notFoundIfNull(mRequest);
		render(mRequest);
	}

	/**
	 * Creates a new idea with details from both the ideas that where requested
	 * to be merged, the method also either merges comments/videos from both
	 * ideas or removes all comments/videos according to the users choices in
	 * the radio button list in the view. It also sends notifications and mails
	 * to a list of users that the user chooses from a check list.If the merge
	 * request searched for by the id is null, the user is redirected to a page,
	 * which shows the user a message that the merge request is not found.Adds the action
	 * done to the action log.If the user is null, ie is no logged in , he will
	 * be redirected to the not logged in page.
	 * 
	 * @author Hesham Massoud
	 * 
	 * @story C3S42
	 * 
	 * @param mergeRequestId
	 *            The id of the merge request that is rejected.
	 * 
	 * @param title
	 *            The title of the new merged idea.
	 * 
	 * @param content
	 *            The content of the new merged idea.
	 * 
	 * @param comments
	 *            A string representing the radio button list,which specifies
	 *            whether the user, has chosen to append all the comments of
	 *            both ideas together, or delete all of them.
	 * 
	 * @param optionOne
	 *            A string representing the first option of the check boxes of
	 *            who to send the notifications to."Idea Creators."
	 * 
	 * @param optionTwo
	 *            A string representing the two option of the check boxes of who
	 *            to send the notifications
	 *            to."Topic/Entity/Organization Followers."
	 * 
	 * @param optionThree
	 *            A string representing the three option of the check boxes of
	 *            who to send the notifications
	 *            to."People who commented on both ideas."
	 * 
	 * @param optionFour
	 *            A string representing the four option of the check boxes of
	 *            who to send the notifications to."Request sender."
	 * 
	 * @param optionFive
	 *            A string representing the five option of the check boxes of
	 *            who to send the notifications
	 *            to."Everyone in the organization."
	 * 
	 * @param optionFive
	 *            A string representing the radio button list,which specifies
	 *            whether the user, has chosen to append all the videos of both
	 *            ideas together, or delete all of them.
	 * */
	public static void mergeIdeas(long mergeRequestId, String title,
			String content, String comments, String optionOne,
			String optionTwo, String optionThree, String optionFour,
			String optionFive, String videos) {
		flash.success("You have succussfully merged the ideas!");
		User user = User.getUserInfo(session.get("username"));
		if (user != null) {
			MergeRequest mergeRequest = MergeRequest.findById(mergeRequestId);
			notFoundIfNull(mergeRequest);
			Idea firstI = mergeRequest.firstIdea;
			Idea secondI = mergeRequest.secondIdea;
			List<Comment> firstIComments = firstI.comments;
			List<Comment> secondIComments = secondI.comments;
			Topic topic = mergeRequest.firstIdea.topic;
			EEntity entity = topic.entity;
			Organization organization = entity.organization;
			LinkedList<Comment> allComments = new LinkedList();
			LinkedList<String> allVideos = new LinkedList();
			LinkedList<User> toBeNotified = new LinkedList();
			Idea mergedIdea = new Idea(title, content, new Date(), topic,
					mergeRequest.sender).save();
			if (comments != null && !comments.isEmpty()) {
				if (comments.equals("yes")) {
					for (Comment comm : firstIComments) {
						copyComment(comm, mergedIdea);
						// allComments.add(comm);
						// comm.idea = mergedIdea;
					}
					for (Comment comm : secondIComments) {
						copyComment(comm, mergedIdea);
						// allComments.add(comm);
						// comm.idea = mergedIdea;
					}
					mergedIdea.comments.addAll(allComments);
					mergedIdea.save();
				}
			}
			if (videos != null && !videos.isEmpty()) {
				if (videos.equals("yes")) {
					for (String v : firstI.videos)
						allVideos.add(v);
					for (String v : secondI.videos)
						allVideos.add(v);
					mergedIdea.videos.addAll(allVideos);
					mergedIdea.save();
				}
			}

			if (optionOne != null && !optionOne.isEmpty()) {
				toBeNotified.add(firstI.creator);
				toBeNotified.add(secondI.creator);
			}
			if (optionTwo != null && !optionTwo.isEmpty()) {
				for (User tFollower : topic.followingUsers)
					toBeNotified.add(tFollower);
				for (User eFollower : entity.followingUsers)
					toBeNotified.add(eFollower);
				for (User oFollower : organization.followingUsers)
					toBeNotified.add(oFollower);
			}
			if (optionThree != null && !optionThree.isEmpty()) {
				for (Comment comment : firstI.comments) {
					toBeNotified.add(comment.creator);
				}
				for (Comment comment : secondI.comments) {
					toBeNotified.add(comment.creator);
				}
			}
			if (optionFour != null && !optionFour.isEmpty()) {
				toBeNotified.add(mergeRequest.sender);
			}
			if (optionFive != null && !optionFive.isEmpty()) {
				List<User> users = User.findAll();
				LinkedList<User> everyoneInOrg = new LinkedList<User>();
				for (User member : users) {
					if (organization.isMember(member.id)) {
						everyoneInOrg.add(member);
					}
				}
				toBeNotified.addAll(everyoneInOrg);
			}
			Notification notification = new Notification("The two ideas "
					+ firstI.title + " and " + secondI.title
					+ " were just merge by " + user.userName
					+ " into the new idea called " + title + ".",
					mergedIdea.id, 4, user, toBeNotified).save();
			Application.sendMail(notification.description,
					"Idea Management:Merge Request Accepted!", toBeNotified);
			String actionMsg = "User name " + user.name
					+ " accepted the merge Request sent by "
					+ mergeRequest.sender.name + " by merging "
					+ mergeRequest.firstIdea.title + " and "
					+ mergeRequest.secondIdea.title + " into " + title;
			new ActionLog(actionMsg, user, null).save();
			mergedIdea.save();

			mergeRequest.cascadeDelete();

			firstI.cascadeDelete();
			secondI.cascadeDelete();
			// topic.deleteIdea(firstI.id);
			// topic.deleteIdea(secondI.id);
			myMergeRequests();
		} else {
			render("Application/notLoggedIn.html");
		}
	}

	/**
	 * 
	 * Creates a new comment from with the same attributes as the given comment,
	 * except for the Idea , which is set to the idea given in the method's
	 * parameters.
	 * 
	 * 
	 * @author Hesham Massoud
	 * 
	 * @story C3S42
	 * 
	 * @param comment
	 *            The id of the merge request that is rejected.
	 * 
	 * @param mergedIdea
	 *            A string representing the delete button, will be used to check
	 *            if it was pressed or not.
	 * 
	 * @return Comment The new comment which is created in this method.
	 * 
	 * */
	public static Comment copyComment(Comment comment, Idea mergedIdea) {
		User commenter = comment.creator;
		String newCont = comment.content;
		Double rating = comment.rating;
		Comment newComment = new Comment(rating, newCont, commenter,
				mergedIdea, comment.generatedLog).save();
		mergedIdea.save();
		return newComment;
	}

	/**
	 * Sends a notification to the user who sent the request telling him that
	 * the request was rejected, also according to which button was pushed the
	 * corresponding action is done, as in , if he pushed
	 * "just reject the request", no mail is sent just a notification telling
	 * the user that the request was rejected. However, if the
	 * "send mail and reject request" button was pushed, a mail is sent with to
	 * the sender telling him why the request was rejected.Adds the action
	 * done to the action log.If the user is null, ie is no logged in , he will 
	 * be redirected to the not logged in page.
	 * 
	 * @author Hesham Massoud
	 * 
	 * @story C3S42
	 * 
	 * @param requestId
	 *            The id of the merge request that is rejected.
	 * 
	 * @param delete
	 *            A string representing the delete button, will be used to check
	 *            if it was pressed or not.
	 * 
	 * @param send
	 *            A string representing the send button, will be used to check
	 *            if it was pressed or not.
	 * 
	 * @param mail
	 *            The mail content the user writes in the mail body textbox.
	 * 
	 * */
	public static void rejectRequest(long requestId, String delete,
			String send, String mail) {
		flash.success("You have succussfully rejected the idea!");
		User user = User.getUserInfo(session.get("username"));
		if (user != null) {
			MergeRequest request = MergeRequest.findById(requestId);
			notFoundIfNull(request);
			String whyRejected = "";
			LinkedList<User> recieveNot = new LinkedList();
			recieveNot.add(request.sender);
			if (send != null && !send.isEmpty()) {
				whyRejected += mail;
			}
			Notification notification = new Notification(user.userName
					+ " rejected your request for merging : "
					+ request.firstIdea.title + " and "
					+ request.secondIdea.title, request.id, 17, user,
					recieveNot).save();
			if (whyRejected == "")
				Application.sendMail(notification.description,
						"Idea Management:Merge Request Rejected!", recieveNot);
			else
				Application.sendMail(notification.description
						+ "\nThe Reason of rejection:-\n" + whyRejected,
						"Idea Management:Merge Request Rejected!", recieveNot);
			request.sender.mergeRequestsSent.remove(request);
			request.sender.save();
			List<User> recepients = request.recievers;
			for (User reciever : recepients) {
				reciever.mergeRequestsRecieved.remove(request);
				reciever.save();
			}
			String actionMsg = "User name " + user.name
			+ " rejected the merge Request sent by "
			+ request.sender.name + " to merge "
			+ request.firstIdea.title + " and "
			+ request.secondIdea.title;
			new ActionLog(actionMsg, user, null).save();
			request.cascadeDelete();
			// request.delete();
			ProfileController.myMergeRequests();
		} else {
			render("Application/notLoggedIn.html");
		}
	}

	/**
	 * A method to view the "My Drafts" page for each user, which shows all the
	 * drafts this user has saved, this includes topic requests and ideas.It
	 * renders a list of all requests saved as drafts and a list of all ideas
	 * saved as drafts for this specific user.If the user is null, ie is no logged in
	 * ,he will be redirected to the not logged in page.
	 * 
	 * @author Hesham Massoud
	 * 
	 */
	public static void myDrafts() {
		String username = session.get("username");
		User user = User.find("byUsername", username).first();
		if (user != null) {
			List<Idea> ideas = user.createdIdeas;
			List<Idea> drafts = new ArrayList<Idea>();
			List<Topic> topics = user.createdTopics;
			List<Topic> draftRequests = new ArrayList<Topic>();
			for (int i = 0; i < ideas.size(); i++) {
				if (ideas.get(i).isDraft) {
					drafts.add(ideas.get(i));
				}
			}
			for (int i = 0; i < topics.size(); i++) {
				if (topics.get(i).status == 3 && topics.get(i).isDraft) {
					draftRequests.add(topics.get(i));
				}
			}
			render(draftRequests, drafts);
		} else {
			render("Application/notLoggedIn.html");
		}
	}

	/**
	 * Renders the ID of the draft idea that will be viewed.
	 * 
	 * @author Hesham Massoud
	 * 
	 * @param draftID
	 *            is the ID of the draft idea that will be viewed.
	 * */
	public static void viewDraft(long draftID) {
		Idea draft = Idea.findById(draftID);
		notFoundIfNull(draft);
		render(draft);
	}

	/**
	 * 
	 * Renders the ID of the draft topic request that will be viewed.
	 * 
	 * @author Hesham Massoud
	 * 
	 * @param draftRequestID
	 *            is the ID of the draft topic request that will be viewed.
	 * */
	public static void viewDraftRequest(long draftRequestID) {
		Topic requestDraft = Topic.findById(draftRequestID);
		notFoundIfNull(requestDraft);
		render(requestDraft);
	}

	/**
	 * Enables the user to edit an idea after it has been saved as a draft. It
	 * takes the title and the content of the draft idea, 3 strings which
	 * represent three submits in a form and the ID of the draft idea. This
	 * method checks whether the button that was clicked was
	 * "save the idea as draft" or "delete idea" or "post the idea". And it
	 * performs the corresponding operation to the clicked button. If an idea
	 * was posted, notifications and mails will be sent to whoever is meant to
	 * be notified..Adds the action done to the action log.If the user is null,
	 * ie is no logged in , he will be redirected to the not logged in page.
	 * 
	 * @author Hesham Massoud
	 * 
	 * @param title
	 *            is the title of the draft idea that was either already saved,
	 *            or the one that will be overwritten.
	 * @param content
	 *            is the content of the draft idea that was either already
	 *            saved, or the one that will be overwritten.
	 * @param postButton
	 *            is the String which represents the "Post idea" button.
	 * @param draftButton
	 *            is the String which represents the "Save idea as draft"
	 *            button.
	 * @param deleteButton
	 *            is the String which represents the "Delete idea" button.
	 * @param draftId
	 *            is the ID of the draft idea that we will edit.
	 * 
	 * */
	public static void editDraft(String title, String content,
			String postButton, String draftButton, String deleteButton,
			long draftId) {
		String username = session.get("username");
		Idea idea = Idea.findById(draftId);
		notFoundIfNull(idea);
		User user = User.find("byUsername", username).first();
		if (user != null) {
			if ((postButton != null && !postButton.isEmpty())) {

				idea.title = title;
				idea.content = content;
				idea.isDraft = false;
				idea.date = new Date();
				idea.save();
				LinkedList<User> toBeNotified = new LinkedList<User>();
				Topic topic = idea.topic;
				EEntity entity = topic.entity;
				Organization organization = entity.organization;
				for (User topicFollowers : topic.followingUsers)
					toBeNotified.add(topicFollowers);
				for (User entityFollowers : entity.followingUsers)
					toBeNotified.add(entityFollowers);
				for (User organizationFollowers : organization.followingUsers)
					toBeNotified.add(organizationFollowers);
				toBeNotified.add(organization.getOrganizationLead());
				List<User> organizers = entity.getOrganizers();
				toBeNotified.addAll(organizers);
				Notification notification = new Notification(user.userName
						+ " proposed a new idea with the title: " + idea.title
						+ ".", idea.id, 4, user, toBeNotified).save();
				Application
						.sendMail(
								notification.description
										+ "\nYou recieved this mail, because you are either following the organization: "
										+ organization.name
										+ " or the entity: "
										+ entity.name
										+ " or the topic: "
										+ topic.name
										+ ".\nYou will find this new idea in the topic: "
										+ topic.name + ".",
								"Idea Management:Topic Request!", toBeNotified);
				String actionMsg = user.userName
						+ " proposed a new idea with the title: " + idea.title
						+ " into the topic " + idea.topic.name + ".";
				new ActionLog(actionMsg, user, null).save();
				flash.success("Idea Successfully posted");
				myDrafts();
				// Idea successfully posted.
			} else {
				if ((draftButton != null && !draftButton.isEmpty())) {
					idea.title = title;
					idea.content = content;
					idea.date = new Date();
					idea.save();
					String actionMsg = user.userName
					+ " saved a draft idea with the title " + idea.title + ".";
					new ActionLog(actionMsg, user, null).save();
					flash.success("Idea Successfully saved as draft.");
					myDrafts();
					// Idea successfully saved as draft.
				} else {
					user.createdIdeas.remove(idea);
					user.save();
					String actionMsg = user.userName
					+ " deleted a draft idea with the title " + idea.title + ".";
					new ActionLog(actionMsg, user, null).save();
					idea.cascadeDelete();
					// idea.delete();
					// Cache.safeDelete("idea_" + draftId);
					flash.success("Idea successfully deleted.");
					myDrafts();
				}// Are you sure you want to delete?
			}
		} else {
			render("Application/notLoggedIn.html");
		}
	}

	/**
	 * Enables the user to edit a topic request after it has been saved as a
	 * draft. It takes the name and the description of the topic request, 3
	 * strings which represent three submits in a form and the ID of the draft
	 * topic request. This method checks whether the button that was clicked was
	 * "save the idea as draft" or "delete idea" or "post the idea". And it
	 * performs the corresponding operation to the clicked button. If the
	 * request draft is sent notifications and mails will be sent to whoever is
	 * meant to be notified.Adds the action done to the action log.If the user is null,
	 * ie is no logged in , he will be redirected to the not logged in page.
	 * 
	 * @author Hesham Massoud
	 * 
	 * @param name
	 *            is the title of the draft idea that was either already saved,
	 *            or the one that will be overwritten.
	 * @param description
	 *            is the content of the draft idea that was either already
	 *            saved, or the one that will be overwritten.
	 * @param postButton
	 *            is the String which represents the "Post idea" button.
	 * @param draftButton
	 *            is the String which represents the "Save idea as draft"
	 *            button.
	 * @param deleteButton
	 *            is the String which represents the "Delete idea" button.
	 * @param draftRequestId
	 *            is the ID of the draft idea that we will edit.
	 * 
	 * */
	public static void editDraftRequest(String name, String description,
			String postButton, String draftButton, String deleteButton,
			long draftRequestId) {
		String username = session.get("username");
		Topic request = Topic.findById(draftRequestId);
		notFoundIfNull(request);
		User user = User.find("byUsername", username).first();
		if (user != null) {
			if ((postButton != null && !postButton.isEmpty())) {
				request.name = name;
				request.description = description;
				request.isDraft = false;
				request.date = new Date();
				request.save();
				LinkedList<User> toBeNotified = new LinkedList<User>();
				EEntity entity = request.entity;
				for (User organizer : entity.getOrganizers())
					toBeNotified.add(organizer);
				Notification notification = new Notification(
						user.userName
								+ " sent you a request to create a new topic with name: "
								+ request.name + ".", entity.id, 18, user,
						toBeNotified).save();
				Application
						.sendMail(
								notification.description
										+ "\nApprove or Reject the request by viewing your requests and opening this request.",
								"Idea Management:Topic Request!", toBeNotified);
				flash.success("Request successfully Sent.");
				String actionMsg = user.userName
				+ " sent a topic request with the name "+ request.name 
				+ ", to the organizers of " + entity.name + " in the Organization "+ entity.organization.name + ".";
				new ActionLog(actionMsg, user, null).save();
				myDrafts();
				// Request successfully posted.
			} else {
				if ((draftButton != null && !draftButton.isEmpty())) {
					request.name = name;
					request.description = description;
					request.date = new Date();
					request.save();
					flash.success("Request Successfully saved as draft.");
					String actionMsg = user.userName
					+ " saved a draft topic request with the title " + request.name;
					new ActionLog(actionMsg, user, null).save();
					myDrafts();
					// Request successfully saved as draft.
				} else {
					user.createdTopics.remove(request);
					String actionMsg = user.userName
					+ " deleted a draft topic request with the title " + request.name;
					new ActionLog(actionMsg, user, null).save();
					user.save();
					// request.delete();
					// Cache.safeDelete("request_" + draftRequestId);
					request.cascadeDelete();
					flash.success("Request successfully deleted.");
					myDrafts();
				}// Are you sure you want to delete?
			}
		} else {
			render("Application/notLoggedIn.html");
		}
	}

	/**
	 * Renders a page for all the merge requests received by the user,if this
	 * list is null the user is redirected which renders that that thing is not
	 * found, if he's not logged in, it renders to the "notLoggedIn.html".
	 * 
	 * @author Hesham Massoud
	 * 
	 * @story C3S41
	 * 
	 * */

	public static void myMergeRequests() {
		User user = User.getUserInfo(session.get("username"));
		if (user != null) {
			List<MergeRequest> requests = user.mergeRequestsRecieved;
			notFoundIfNull(requests);
			render(requests);
		} else {
			render("Application/notLoggedIn.html");
		}
	}
}
